package com.motu.vertx.module.utility.webtool;

import com.motu.vertx.module.utility.postgresql.PostgreUtils;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.sql.SQLClient;
import io.vertx.ext.web.RoutingContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;


public class BaseWebHandlerPQ extends BaseWebHandler {
	public static final String commonWebPath = "com.motu.vertx.module.utility.webhandler.";
	private static final Logger logger = LoggerFactory.getLogger(BaseWebHandlerPQ.class);
	protected static final int TOKEN_EXPIRE_TIME = 86400*7;//有效期两天
	
	/***
	 * 根据搜索条件列表，从表中搜索数据, pq数据库
	 */
	protected static void searchFromTablePQ(RoutingContext routingContext,SQLClient jdbcClient,JsonObject json,String tableName,List<SearchCondition> scList){
		JsonArray params1 = new JsonArray();
		String str_where = getSearchString(scList, json, params1);
		String sortColumn = "id desc";//默认按id排序
		if (json.containsKey("orderby")){
			sortColumn = json.getString("orderby");
		}
		String str = " FROM " + tableName + " where 1=1 " + str_where;
		String sql1 = "select count(1) " + str +";";
		String columns = "*";
		if(json.containsKey("columns")){
			columns = getColumnsString(json.getJsonArray("columns"));
		}
		String sql2 = "select " + columns + " " + str + " order by " + sortColumn + " limit ? offset ?; ";
		JsonArray params2 = params1.copy();
		int pageNo = json.getInteger("pageNo");
		int pageSize = json.getInteger("pageSize");
		int start = pageNo*pageSize;
		params2.add(pageSize);
		params2.add(start);
		searchFromTablePQ(routingContext, jdbcClient, sql1, params1, sql2, params2);
	}
	
	/***
	 * 搜索数据，旧接口, pq数据库
	 */
	public static void searchFromTablePQ(RoutingContext routingContext,SQLClient jdbcClient, String sql1,JsonArray params1,String sql2,JsonArray params2){
		HttpServerResponse response = routingContext.response();
		Promise<JsonArray> fut1 = Promise.promise(); //定义最终的操作
		Promise<JsonArray> fut2 = Promise.promise();//定义第一个操作
		JsonObject result = new JsonObject();
		PostgreUtils.queryJsonArrayFromDb(jdbcClient, sql1, params1, fut1);//执行第一个查询
		PostgreUtils.queryJsonArrayFromDb(jdbcClient, sql2, params2, fut2);//执行第二个查询
		Future.all(fut1.future(), fut2.future()).onComplete(res->{
			if(res.succeeded()) {
				int total = fut1.future().result().getJsonObject(0).getInteger("count");
				result.put("total", total);
				JsonArray list = fut2.future().result();
				result.put("rows",list);
				sendHttpResponse(response, result);
			}else {
				sendHttpResponseError(response,  res.cause().getMessage());
				logger.error("####### searchFromTable error:"+res.cause().getMessage());
			}
		});
	}
	
	/***
	 * 插入一条数据，并返回http请求的结果
	 */
	public static Future<Long> addToTablePQ(RoutingContext routingContext, SQLClient jdbcClient, String tableName, JsonObject jsonDecrypt){
		Promise<Long> fut = Promise.promise();
		HttpServerResponse response = routingContext.response();
		JsonObject json = jsonDecrypt != null?jsonDecrypt:routingContext.body().asJsonObject().getJsonObject("pdata");
		Iterator<Entry<String, Object>> it = json.iterator();
		JsonArray params = new JsonArray();
		String keys = "";
		String values = "";
		while(it.hasNext()){
			Entry<String, Object> en = it.next();
			keys += en.getKey();
			values += "?";
			if(it.hasNext()){
				keys += ",";
				values += ",";
			}
			params.add(en.getValue());
		}
		String sql = "insert into "+tableName+"("+keys+") values("+values+") RETURNING id;";
		PostgreUtils.updateToDb(jdbcClient, sql, params, handler->{
			if(handler.succeeded()){
				sendHttpResponse(response, new JsonObject());
				sendLog(routingContext, new JsonObject());
			}else{
				logger.error(handler.cause().getMessage());
				sendHttpResponseError(response, handler.cause().getMessage());
				fut.complete((long) 0);
			}
		});
		return fut.future();
	}
	
	/***
	 * 从表中删除数据
	 */
	public static Future<JsonArray> deleteFromTablePQ(RoutingContext routingContext,SQLClient jdbcClient,String tableName){
		Promise<JsonArray> fut = Promise.promise();
		HttpServerResponse response = routingContext.response();
		JsonObject json = routingContext.body().asJsonObject().getJsonObject("pdata");
		JsonArray idList = json.getJsonArray("ids");
		JsonArray params = new JsonArray();
		String sql = "delete from "+tableName+"  where id in (";
		for(int i = 0;i<idList.size();i++){
			sql += "?";
			if(i < idList.size()-1){
				sql += ",";
			}
			params.add(idList.getLong(i));
		}
		sql += ");";
		PostgreUtils.updateToDb(jdbcClient, sql, params, handler->{
			if(handler.succeeded()){
				JsonObject result = new JsonObject();
				sendHttpResponse(response, result);
				sendLog(routingContext, result);
				fut.complete(idList);
			}else{
				logger.error(handler.cause().getMessage());
				sendHttpResponseError(response, handler.cause().getMessage());
				fut.complete(null);
			}
		});
		return fut.future();
	}
	
	/***
	 * 搜索一条数据，并取出关联的子表信息，如act和actdetail
	 */
	public static void getOneWithDetailPQ(RoutingContext routingContext,SQLClient jdbcClient1,String sql1,JsonArray params1,SQLClient jdbcClient2,String sql2,JsonArray params2){
		HttpServerResponse response = routingContext.response();
		Promise<JsonArray> fut1 = Promise.promise();//定义第一个操作
		Promise<JsonArray> futn = Promise.promise(); //定义最终的操作
		JsonObject result = new JsonObject();
		PostgreUtils.queryJsonArrayFromDb(jdbcClient1, sql1,params1,fut1);//执行第一个查询
		fut1.future().onSuccess(handler1-> {
			JsonArray list = handler1;
			if(list.size() == 1){
				JsonObject obj = list.getJsonObject(0);
				result.put("info",obj);
				PostgreUtils.queryJsonArrayFromDb(jdbcClient2, sql2,params2, futn);//执行第二个查询
			}else{
				futn.fail("数据库查询失败，请输入有效的id！");
			}
		}).onFailure(futn::fail);

		futn.future().onComplete(handler->{//设置最终处理函数
			if(handler.succeeded() && handler.result() != null){
				JsonArray list = handler.result();
				result.put("details",list);
				sendHttpResponse(response, result);
			}else{
				sendHttpResponseError(response, handler.cause().getMessage());
			}
			return;
		});
	}
}
